package com.wpi.iCoach;

import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;

/**
 * This activity class displays a selectable list of locations stored in the application
 * database that pertain to the selectivity filters used. This activity uses three drop-down
 * selectors to filter and sort the locations: sort by..., filter location type, and display
 * K number of results per page.
 * (Paging functionality not implemented. Only the first K results will ever be displayed.
 * This functionality requires a rewrite of the DBLocMgr.) 
 * 
 * @author Kenneth J. Loomis (kjloomis),
 *         Kevin Chen(xchen)
 * @version June 2012
 */
public class FindSaved extends ListActivity implements LocationListener {

	/** Down-down spinner selector for the location types */
	private static Spinner spTypes;
	
	/** Integer representation of the position of the selected location type */
	private int posTypes;
	
	/**
	 * String array of the number of results (K) shown per page.
	 * This is bound a predefined array.
	 * @see res/values/strings.xml
	 */
	private String optCounts [];
	
	/** Drop-down spinner selector for the number of results (K) shown */
	private static Spinner spCounts;
	
	/** Integer representation of the position of number of results (K) shown selected */
	private int posCounts;

	/**
	 * String array of the sort options. This is bound a predefined array.
	 * @see res/values/strings.xml
	 */
	private String optOrder [];
	
	/** Drop-down spinner selector for the sort by options. */
	private static Spinner spOrder;
	
	/** Integer representation for the position of the sort by option selected. */
	private int posOrder;
	
	/**
	 * Array of selected location types to be displayed. This will only ever be one type
	 * at this point, but allows for future extended flexibility of allowing the user to
	 * display more than one location type in the results list. 
	 */
	private String selTypes [] = new String[1]; // Will only ever be one type at this point
	
	/**
	 * Integer representing the number of results to be displayed.
	 */
	private Integer valK;
	
	/**  */
	private LocationManager mloc;
	
	LocationAdapter locAdptr;
	CurrentMap cloc;
	LocationEntry menuList [];
	Location curLoc;
	LocDBMgr locMngr = new LocDBMgr ( FindSaved.this );
	
	/**
	 * Called when the activity is paused. Removes the location updates notification.
	 * (This function should not be called, executes when the activity is paused.)
	 */
	@Override
	protected void onPause() {
		super.onPause();
		if ( mloc != null )
			mloc.removeUpdates ( FindSaved.this );
	}

	/**
	 * Called when the activity is resumed. Resets the location updates notification.
	 * (This function should not be called, executes when the activity is resumed.)
	 */
	@Override
	protected void onResume() {
		super.onResume();
		if ( mloc != null )
			mloc.requestLocationUpdates ( LocationManager.GPS_PROVIDER, 60000, 1, FindSaved.this );
	}

	/**
	 * Handles when a location item in the list of locations is clicked by the user. The
	 * LocationView activity is loaded and the information about the selected location is
	 * passed to this activity.
	 * (This function should not be called, executes when a click event occurs.)
	 * 
	 * @param l (The listview were the click occurred.)
	 * @param v (The view that was clicked.)
	 * @param position (The position in the array of displayed location of the clicked location.)
	 * @param id (The id of the clicked view.)
	 */
	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		super.onListItemClick(l, v, position, id);
		
		LocationEntry thisLoc = menuList [ position ];
		
		cloc.setThereLat(thisLoc.lat);
		cloc.setThereLon(thisLoc.lon);
		cloc.setAll( thisLoc.locName, "# Visits: " + Integer.toString( thisLoc.visit ),  thisLoc.dist, thisLoc.likeness );
		
		// Kevin's new code
		String rating = Float.toString(cloc.getRating());
		String thereLat = Double.toString(cloc.getThereLat());
		String thereLon = Double.toString(cloc.getThereLon());
		String hereLat = Double.toString(cloc.getHereLat());
		String hereLon = Double.toString(cloc.getHereLon());
		
		String[] location = {cloc.getName(), cloc.getVisits(), cloc.getDistance(), rating, thereLat, thereLon, hereLat, hereLon};
		Intent i = new Intent("com.wpi.iCoach.LOCATIONVIEW");
		Bundle extras = new Bundle();
		extras.putStringArray("location", location);
		i.putExtras(extras);
		startActivity(i);

	}

	/**
	 * Instantiates the activity. Binds the member arrays to those located in res/values/strings.xml. 
	 * Binds the member drop-down selectors (spinners) to the graphical representations of those items
	 * found in res/layout/locationlist.xml. Also creates listeners for each of these spinner items to 
	 * handle when the selection of these spinners changes. Initializes the location update listener to
	 * poll the location manager for changes in the user location.
	 * (This function should not be called, executes when the activity is created.)
	 * 
	 *  @param savedInstanceState
	 *  @see res/layout/strings.xml
	 *  @see res/layout/locationlist.xml
	 */
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView ( R.layout.loclistmain );
		
		cloc = new CurrentMap();
		
		/* First setup spinner buttons. */

		spTypes = (Spinner) findViewById ( R.id.spType );
		spTypes.setAdapter( new ArrayAdapter<String> ( this,
				R.layout.spinneritem, LocDBMgr.LOC_TYPES ) );
		spTypes.setOnItemSelectedListener( new OnItemSelectedListener () {

			/**
			 * Stores the selected location type value in the drop-down spinner list
			 * and calls UpdateList() to re-populate the location list.
			 * (This function should not be called, executes when the spinner selection changes.)
			 * @param arg0 (The AdapterView associated with this spinner.)
			 * @param arg1 (The spinner view.)
			 * @param arg2 (The position of the selected item in the drop-down.)
			 * @param arg3 (The id of the view.)
			 * @see UpdateList()
			 */
			@Override
			public void onItemSelected(AdapterView<?> arg0, View arg1,
					int arg2, long arg3) {
				// TODO Auto-generated method stub
				posTypes = arg0.getSelectedItemPosition();
				selTypes [0] = Integer.toString( posTypes );
				UpdateList();
			}

			/**
			 * Current does nothing. Uses the previous selection if no new selection made.
			 * (This function should not be called, executes when the spinner was opened 
			 * but the selection does not change.)
			 * @param arg0 (The AdapterView associated with this spinner.)
			 */ 
			@Override
			public void onNothingSelected(AdapterView<?> arg0) {
				// TODO Auto-generated method stub
			}
			
		}
		);
		
		optCounts = getResources().getStringArray( R.array.ResultsCount );
		spCounts = (Spinner) findViewById ( R.id.spHowMany );
		spCounts.setAdapter( new ArrayAdapter<String> ( this,
				R.layout.spinneritem, optCounts ) );
		spCounts.setOnItemSelectedListener( new OnItemSelectedListener () {

			/**
			 * Stores the selected count (K) value in the drop-down spinner list
			 * and calls UpdateList() to re-populate the location list.
			 * (This function should not be called, executes when the spinner selection changes.)
			 * @param arg0 (The AdapterView associated with this spinner.)
			 * @param arg1 (The spinner view.)
			 * @param arg2 (The position of the selected item in the drop-down.)
			 * @param arg3 (The id of the view.)
			 * @see UpdateList()
			 */
			@Override
			public void onItemSelected(AdapterView<?> arg0, View arg1,
					int arg2, long arg3) {
				// TODO Auto-generated method stub
				posCounts = arg0.getSelectedItemPosition();
				valK = Integer.parseInt( optCounts [ posCounts ] );
				UpdateList();
			}

			/**
			 * Current does nothing. Uses the previous selection if no new selection made.
			 * (This function should not be called, executes when the spinner was opened 
			 * but the selection does not change.)
			 * @param arg0 (The AdapterView associated with this spinner.)
			 */
			@Override
			public void onNothingSelected(AdapterView<?> arg0) {
				// TODO Auto-generated method stub
			}
			
		}
		);
		
		optOrder = getResources().getStringArray( R.array.OrderBy );
		spOrder = (Spinner) findViewById ( R.id.spOrder );
		spOrder.setAdapter( new ArrayAdapter<String> ( this,
				R.layout.spinneritem, optOrder ) );
		spOrder.setOnItemSelectedListener( new OnItemSelectedListener () {

			@Override
			/**
			 * Stores the selected sort by value in the drop-down spinner list
			 * and calls UpdateList() to re-populate the location list.
			 * (This function should not be called, executes when the spinner selection changes.)
			 * @param arg0 (The AdapterView associated with this spinner.)
			 * @param arg1 (The spinner view.)
			 * @param arg2 (The position of the selected item in the drop-down.)
			 * @param arg3 (The id of the view.)
			 * @see UpdateList()
			 */
			public void onItemSelected(AdapterView<?> arg0, View arg1,
					int arg2, long arg3) {
				posOrder = arg0.getSelectedItemPosition();
				UpdateList();
			}

			/**
			 * Current does nothing. Uses the previous selection if no new selection made.
			 * (This function should not be called, executes when the spinner was opened 
			 * but the selection does not change.)
			 * @param arg0 (The AdapterView associated with this spinner.)
			 */
			@Override
			public void onNothingSelected(AdapterView<?> arg0) {
				// TODO Auto-generated method stub
			}
			
		}
		);
		
		// Default spinner values
		selTypes [0] = "0";
		valK = 3;
		
		mloc = ( LocationManager ) getSystemService ( Context.LOCATION_SERVICE );
	    //Criteria crit = new Criteria();
	    //Location curLoc = mloc.getLastKnownLocation( mloc.getBestProvider( crit, false ) );
		mloc.requestLocationUpdates ( LocationManager.GPS_PROVIDER, 5000, 1, FindSaved.this );

		curLoc = mloc.getLastKnownLocation( LocationManager.GPS_PROVIDER );
		UpdateList ( );
		locAdptr =  new LocationAdapter ( FindSaved.this, R.layout.locationlist, menuList );
		setListAdapter ( locAdptr );
	}

	/**
	 * This is the listener that is executed when the GPS location of the user has changed. This
	 * ensures that the location list is always up-to-date based on the users current location.
	 * (This function should not be called; it executes when the user's GPS location changes.)
	 * @param location (The current location as generated by the Location Manager.)
	 */
	@Override
	public void onLocationChanged(Location location) {
		curLoc = location;
		UpdateList();
	}

	/** 
	 * Currently does nothing.
	 * (This function should not be called; it executes when the user's GPS cellular provider is disabled.)
	 */
	@Override
	public void onProviderDisabled(String provider) {
		// TODO Auto-generated method stub
		
	}

	/** 
	 * Currently does nothing.
	 * (This function should not be called; it executes when the user's GPS cellular provider is enabled.)
	 */
	@Override
	public void onProviderEnabled(String provider) {
		// TODO Auto-generated method stub
		
	}

	/** 
	 * Currently does nothing.
	 * (This function should not be called; it executes when the user's GPS cellular provider's status changes.)
	 */
	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
		// TODO Auto-generated method stub
		
	}
	
	/**
	 * Updates the displayed list of locations by retrieving a new array of locations from the Location Database
	 * Manager and creating a new LocationAdapter which is in-turn consumed by the ListAdapter.
	 * (This function takes no arguments.)
	 * @see LocationAdapter.java 
	 */
	private void UpdateList ( )
	{
		locMngr.Open ( );
		if ( curLoc != null )
		{
			menuList = locMngr.GetTopK ( curLoc.getLatitude(), curLoc.getLongitude(), selTypes, valK, posOrder );
			//cloc.setHere( curLoc.getLatitude(), curLoc.getLongitude() );
			// Kevin's new code
			cloc.setHereLat(curLoc.getLatitude());
			cloc.setHereLon(curLoc.getLongitude());
		}
		else
		{
			menuList = locMngr.GetTopK ( 0, 0, selTypes, valK, posOrder );
			//cloc.setHere( 0, 0 );
			// Kevin's new code
			cloc.setHereLat(0);
			cloc.setHereLon(0);
			
		}
		locMngr.Close ( );
		
		locAdptr =  new LocationAdapter ( FindSaved.this, R.layout.locationlist, menuList );
		setListAdapter ( locAdptr );
	}
	
	
}
